home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / lib / bezier.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  3KB  |  138 lines

  1.  
  2. /*
  3.  *    @(#) bezier.c 9.1 93/06/14 SCOINC
  4.  */
  5. /*
  6.  *  Ported from CGI to X11 on 20 Apr 1993 by rr@sco.com
  7.  */
  8. /*    X11 library module to allow drawing of curves in the plane
  9.  *    utilizing the method due to P. Bezier, of the French firm
  10.  *    Regie Renault.
  11.  *
  12.  *    Intended to be used as follows :
  13.  *    Draw_bez(display,window,pixmap,gc,ctrl_pts,num_pts,num_steps)
  14.  *    where "display" is the X11 display;
  15.  *          "window" is a drawable;
  16.  *          "pixmap" is a drawable;
  17.  *        "gc" is a graphical context (GC)
  18.  *          "ctrl_pts" is an array of pointers each pointing to 
  19.  *        an array of control points in the form ctrl_pts[i,j] 
  20.  *        with i the i'th point and j the 
  21.  *        j'th coordinate (of two) in VDC units;
  22.  *          "num_pts" is the number of control points.
  23.  *          "num_steps" is the number of steps to take in drawing the curve.
  24.  *    
  25.  *    Coded in C by Ron Record (sco!rr) Jan. 4, 1988
  26.  */
  27.  
  28. #include <X11/Xlib.h>
  29.  
  30. /* 
  31.  * C(n,i) is the binomial coefficient, C(n,i) = n!/(i!(n-i)!).
  32.  */
  33.  
  34. static double mn[2];
  35.  
  36. long
  37. C(n,i)
  38. int n, i;
  39. {
  40.     int j;
  41.     long a;
  42.  
  43.     a = 1;
  44.     for (j=i+1;j<=n;j++)
  45.         a*=j;
  46.     for (j=2;j<=(n-i);j++)
  47.         a/=j;
  48.     return(a);
  49. }
  50.  
  51. /*
  52.  * B_blend() is the "blending function" representing the influence that
  53.  * each control point has on the curve at time u
  54.  */
  55.  
  56. double
  57. B_blend(i,n,u)
  58. int i, n;
  59. double u;
  60. {
  61.     int j;
  62.     double v;
  63.  
  64.     v = (double)C(n,i);
  65.     for (j=1;j<=i;j++)
  66.         v *= u;
  67.     for (j=1;j<=(n-i);j++)
  68.         v *= (1.0-u);
  69.     return(v);
  70. }
  71.  
  72. /*
  73.  * Compute the xy coordinates of the curve at time t
  74.  */
  75.  
  76. double *
  77. Bezier(t,n,p)
  78. double t;
  79. int n;
  80. int *p[];
  81. {
  82.     double b;
  83.     double *xy;
  84.     int i;
  85.  
  86.     xy = mn;
  87.     xy[0] = xy[1] = 0.0;
  88.     for (i=0;i<=n;i++) {
  89.         b = B_blend(i,n,t);
  90.         xy[0] += ((double)p[i][0]*b);
  91.         xy[1] += ((double)p[i][1]*b);
  92.     }
  93.     return(xy);
  94. }
  95.  
  96. /*
  97.  * Draw_bez() is called from the application program with arguments an
  98.  * opened display, a drawable, a graphical context, an array of pointers 
  99.  * to integer coordinates specifying the control points, the number of 
  100.  * control points minus one, and the number of steps for each curve.
  101.  */
  102.  
  103. Draw_bez(dpy,w,p,gc,ctrl_pts,num_pts,num_steps)
  104. Display *dpy;
  105. Window w;
  106. Pixmap p;
  107. GC gc;
  108. int *ctrl_pts[];
  109. int num_pts,num_steps;
  110. {
  111.     int i;
  112.     double u;
  113.     double *coord;
  114.     XPoint points[2];
  115.  
  116.     for (i=0;i<num_steps;i++) {
  117.         u = (double)i/(double)num_steps;
  118.         coord = Bezier(u,num_pts,ctrl_pts);
  119.         if (i == 0) {
  120.             points[0].x = (int)coord[0];
  121.             points[0].y = (int)coord[1];
  122.             points[1].x = (int)coord[0];
  123.             points[1].y = (int)coord[1];
  124.         }
  125.         else {
  126.             points[0].x = points[1].x;
  127.             points[0].y = points[1].y;
  128.             points[1].x = (int)coord[0];
  129.             points[1].y = (int)coord[1];
  130.         }
  131.         if (p)
  132.             XDrawLines(dpy, p, gc, points, sizeof(points)/sizeof(points[0]),
  133.                         CoordModeOrigin);
  134.         XDrawLines(dpy, w, gc, points, sizeof(points)/sizeof(points[0]),
  135.                     CoordModeOrigin);
  136.     }
  137. }
  138.